class RatingsController < ApplicationController
  caches_page :index

  before_filter :get_type
  before_filter :get_ratings, :only => [:load_ratings, :content]
  
  def index
    # Reset the nav
    @nav_sections = []
    @nav_sections << ["ratings_form"]
  
    @rateable_objects = RateableObject.get_items({:type => @type})
  end
  
  def load_ratings
    return head(404) unless request.xhr? && !params[:guid].blank?
    
    render :json => @your_ratings.to_json
  end
  
  def content
    return head(404) unless request.xhr?
    
    conditions = {:type => @type}
    conditions.merge!({ :creator => params[:creator] }) if params[:creator]
    conditions.merge!({ :genre   => params[:genre]   }) if params[:genre]
    conditions.merge!({ :order   => params[:order]   }) if 
      params[:order] && RateableObject.columns_hash[params[:order].split(' ').first]
    if params[:creator] || params[:genre]
      @reset_filter = true
    end
    
    @rateable_objects = RateableObject.get_items(conditions)
    
    # Special post query sort
    sort_by, order_by = params[:order].to_s.split(' ')
    if !sort_by.blank? && !RateableObject.columns_hash[sort_by]
      sort_by_guid = lambda { |target_guid|
        @rateable_objects.sort!{|x,y|
          get_score = lambda { |rateable_object| 
            r = rateable_object.ratings.select { |r| r.guid == target_guid }.first
            r ? r.score.to_i : 0
          }
          x_score = get_score.call(x)
          y_score = get_score.call(y)
          
          ret = x_score <=> y_score
          ret = ret * -1 if order_by == "DESC"  # Flip sort if DESC
          ret
        }
      }

      case sort_by
        when 'my_score'
          sort_by_guid.call(SECRET["guid"])
        when 'your_score'
          sort_by_guid.call(params[:guid]) unless params[:guid].blank?
      end
    end
    

    render :update do |page|
      page.replace_html(
        'ratings_content',
        :partial => "ratings/content")
    end
  end
  
  def new
    return head(404) if @type.nil?
    return head(404) unless 
      request.post? &&
      params[:commit].to_s == "+"
    
    if @type == "website"
      params[:name] = 
        params[:url] =~ /http:\/\/(w{3}\.|)(.+)(\/|)/ ?
          $2 : params[:url]
    end
    
    return head(404) if 
      RateableObject.find(:first, :conditions => {
        :name       => params[:name].to_s,
        :creator    => params[:creator].to_s})
    
    obj = RateableObject.new({
      :name       => params[:name].to_s,
      :creator    => params[:creator].to_s,
      :genre      => "",
      :url        => params[:url].to_s,
      :rateable_type => @type,
      :suggested_by  => params[:guid].to_s
    })
    
    if obj.save
      # Attach the rating
      if params[:rateable_rating].to_i > 0 && !params[:guid].blank?
        Rating.new({
          :rateable_object    => obj,
          :score              => params[:rateable_rating].to_i,
          :guid               => params[:guid],
          :from_eusden        => params[:guid] == SECRET["guid"]
        }).save
      end
    
      @force_display_type = true if params[:display_type_after_submit].to_i > 0
      @do_not_render_row_class = true
      @your_ratings = {obj.id => params[:rateable_rating].to_i}
      
      render :update do |page|
        page << "Effect.ScrollTo('rateable_objects_list_end', { offset: -100 })"
        page.insert_html(
          :bottom,
          "rateable_objects_list",
          :partial => "ratings/item",
          :object => obj )
        page << "Ratings.updateLastRowClass();"
      end
    else
      head(400)
    end
  end
  
  def vote
    return head(404) unless params[:id].to_i > 0 &&
      request.post? &&
      request.xhr? &&
      params[:score].to_i > 0 &&
      params[:score].to_i <= 10
      
    conditions = { :rateable_object_id   => params[:id].to_i }
    conditions.merge!({:guid => params[:guid]}) unless params[:guid].blank?
    
    rating = Rating.find(:first, :conditions => conditions)
    
    if rating
      rating.score = params[:score].to_i
      rating.save
    else
      rating = Rating.new({
        :rateable_object_id => params[:id].to_i,
        :score              => params[:score].to_i,
        :guid               => params[:guid],
        :from_eusden        => params[:guid] == SECRET["guid"]
      }).save
    end
    
    head(202)
  end
  
  private
    def get_type
      @type = 
        RateableObject::TYPES.include?(params[:type].to_s.downcase) ?
          params[:type].to_s : nil
    end
    
    def get_ratings
      guid = params[:guid].to_s
      @your_ratings = {}
      unless guid.blank?
        Rating.find(:all, :conditions => {:guid => guid }).each do |rating|
          @your_ratings[rating.rateable_object_id] = rating.score.to_i
        end
      end
    end
end
